home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / m92.c < prev    next >
C/C++ Source or Header  |  2000-04-29  |  21KB  |  695 lines

  1. /*****************************************************************************
  2.  
  3.     Irem M92 video hardware, Bryan McPhail, mish@tendril.co.uk
  4.  
  5.     Brief Overview:
  6.  
  7.         3 scrolling playfields, 512 by 512.
  8.         Each playfield can enable rowscroll, change shape (to 1024 by 512),
  9.         be enabled/disabled and change position in VRAM.
  10.  
  11.         Tiles can have several priority values:
  12.             0 = standard
  13.             1 = Top 8 pens appear over sprites (split tilemap)
  14.             2 = Whole tile appears over sprites
  15.             3 = ?  Seems to be the whole tile is over sprites (as 2).
  16.  
  17.         Sprites have 2 priority values:
  18.             0 = standard
  19.             1 = Sprite appears over all tiles, including high priority pf1
  20.  
  21.         Raster interrupts can be triggered at any line of the screen redraw,
  22.         typically used in games like R-Type Leo to multiplex the top playfield.
  23.  
  24. *****************************************************************************
  25.  
  26.     Master Control registers:
  27.  
  28.         Word 0:    Playfield 1 control
  29.             Bit  0x40:  1 = Rowscroll enable, 0 = disable
  30.             Bit  0x10:    0 = Playfield enable, 1 = disable
  31.             Bit  0x04:  0 = 512 x 512 playfield, 1 = 1024 x 512 playfield
  32.             Bits 0x03:  Playfield location in VRAM (0, 0x4000, 0x8000, 0xc000)
  33.         Word 1: Playfield 2 control (as above)
  34.         Word 2: Playfield 3 control (as above)
  35.         Word 3: Raster IRQ position.
  36.  
  37.     The raster IRQ position is offset by 128+8 from the first visible line,
  38.     suggesting there are 8 lines before the first visible one.
  39.  
  40. *****************************************************************************/
  41.  
  42. #include "driver.h"
  43. #include "vidhrdw/generic.h"
  44.  
  45. static struct tilemap *pf3_wide_layer,*pf3_layer,*pf2_layer,*pf1_wide_layer,*pf1_layer,*pf1_hlayer;
  46. static int pf1_control[8],pf2_control[8],pf3_control[8],pf4_control[8];
  47. static int pf1_vram_ptr,pf2_vram_ptr,pf3_vram_ptr;
  48. static int pf1_enable,pf2_enable,pf3_enable;
  49. static int pf1_rowscroll,pf2_rowscroll,pf3_rowscroll;
  50. static int pf1_shape,pf2_shape,pf3_shape;
  51. static int m92_sprite_list;
  52.  
  53. int m92_raster_irq_position,m92_spritechip,m92_raster_machine,m92_raster_enable;
  54. unsigned char *m92_vram_data,*m92_spritecontrol;
  55. int m92_game_kludge;
  56.  
  57. extern void m92_sprite_interrupt(void);
  58.  
  59. /* This is a kludgey speedup that I consider to be pretty ugly..  But -
  60. it gets a massive speed increase (~40fps -> ~65fps).  It works by avoiding
  61. the need to dirty the top playfield twice a frame */
  62. #define RYPELEO_SPEEDUP m92_game_kludge==1
  63.  
  64. /*****************************************************************************/
  65.  
  66. WRITE_HANDLER( m92_spritecontrol_w )
  67. {
  68.     m92_spritecontrol[offset]=data;
  69.  
  70.     /* The games using this sprite chip can autoclear spriteram */
  71.     if (offset==8 && m92_spritechip==1) {
  72. //        logerror("%04x: cleared spriteram\n",cpu_get_pc());
  73.         buffer_spriteram_w(0,0);
  74.         memset(spriteram,0,0x800);
  75.         m92_sprite_interrupt();
  76.     }
  77. }
  78.  
  79. WRITE_HANDLER( m92_spritebuffer_w )
  80. {
  81. //    logerror("%04x: buffered spriteram %d %d\n",cpu_get_pc(),offset,data);
  82.     if (m92_spritechip==0 && offset==0) {
  83.         buffer_spriteram_w(0,0);
  84.         m92_sprite_interrupt();
  85.     }
  86. //    if (m92_spritechip==1)    memset(spriteram,0,0x800);
  87. }
  88.  
  89. /*****************************************************************************/
  90.  
  91. static void get_pf1_tile_info(int tile_index)
  92. {
  93.     int tile,color,pri;
  94.     tile_index = 4*tile_index+pf1_vram_ptr;
  95.  
  96.     tile=m92_vram_data[tile_index]+(m92_vram_data[tile_index+1]<<8);
  97.     color=m92_vram_data[tile_index+2];
  98.     SET_TILE_INFO(0,tile,color&0x3f)
  99.  
  100.     if (m92_vram_data[tile_index+3]&1) pri = 2;
  101.     else if (color&0x80) pri = 1;
  102.     else pri = 0;
  103.  
  104.     tile_info.flags = TILE_FLIPYX((m92_vram_data[tile_index+3] & 0x6)>>1) | TILE_SPLIT(pri);
  105. }
  106.  
  107. static void get_pf1_htile_info(int tile_index)
  108. {
  109.     int tile,color,pri;
  110.     tile_index = 4*tile_index + 0xc000;
  111.  
  112.     tile=m92_vram_data[tile_index]+(m92_vram_data[tile_index+1]<<8);
  113.     color=m92_vram_data[tile_index+2];
  114.     SET_TILE_INFO(0,tile,color&0x3f)
  115.  
  116.     if (m92_vram_data[tile_index+3]&1) pri = 2;
  117.     else if (color&0x80) pri = 1;
  118.     else pri = 0;
  119.  
  120.     tile_info.flags = TILE_FLIPYX((m92_vram_data[tile_index+3] & 0x6)>>1) | TILE_SPLIT(pri);
  121. }
  122.  
  123. static void get_pf1_ltile_info(int tile_index)
  124. {
  125.     int tile,color,pri;
  126.     tile_index *= 4;
  127.     if (pf1_vram_ptr==0x4000) tile_index += 0x4000;
  128.     else if (pf1_vram_ptr==0x8000) tile_index += 0x8000;
  129.  
  130.     tile=m92_vram_data[tile_index]+(m92_vram_data[tile_index+1]<<8);
  131.     color=m92_vram_data[tile_index+2];
  132.     SET_TILE_INFO(0,tile,color&0x3f)
  133.  
  134.     if (m92_vram_data[tile_index+3]&1) pri = 2;
  135.     else if (color&0x80) pri = 1;
  136.     else pri = 0;
  137.  
  138.     tile_info.flags = TILE_FLIPYX((m92_vram_data[tile_index+3] & 0x6)>>1) | TILE_SPLIT(pri);
  139. }
  140.  
  141. static void get_pf2_tile_info(int tile_index)
  142. {
  143.     int tile,color,pri;
  144.     tile_index = 4*tile_index + pf2_vram_ptr;
  145.  
  146.     tile=m92_vram_data[tile_index]+(m92_vram_data[tile_index+1]<<8);
  147.     color=m92_vram_data[tile_index+2];
  148.     SET_TILE_INFO(0,tile,color&0x3f)
  149.  
  150.     if (m92_vram_data[tile_index+3]&1) pri = 2;
  151.     else if (color&0x80) pri = 1;
  152.     else pri = 0;
  153.  
  154.     tile_info.flags = TILE_FLIPYX((m92_vram_data[tile_index+3] & 0x6)>>1) | TILE_SPLIT(pri);
  155. }
  156.  
  157. static void get_pf3_tile_info(int tile_index)
  158. {
  159.     int tile,color,pri;
  160.     tile_index = 4*tile_index + pf3_vram_ptr;
  161.     tile=m92_vram_data[tile_index]+(m92_vram_data[tile_index+1]<<8);
  162.     color=m92_vram_data[tile_index+2];
  163.  
  164.     if (color&0x80) pri = 1;
  165.     else pri = 0;
  166.  
  167.     SET_TILE_INFO(0,tile,color&0x3f)
  168.     tile_info.flags = TILE_FLIPYX((m92_vram_data[tile_index+3] & 0x6)>>1) | TILE_SPLIT(pri);
  169. }
  170.  
  171. static void get_pf1_wide_tile_info(int tile_index)
  172. {
  173.     int tile,color,pri;
  174.     tile_index = 4*tile_index + pf1_vram_ptr;
  175.  
  176.     tile=m92_vram_data[tile_index]+(m92_vram_data[tile_index+1]<<8);
  177.     color=m92_vram_data[tile_index+2];
  178.     SET_TILE_INFO(0,tile,color&0x3f)
  179.  
  180.     if (m92_vram_data[tile_index+3]&1) pri = 2;
  181.     else if (color&0x80) pri = 1;
  182.     else pri = 0;
  183.  
  184.     tile_info.flags = TILE_FLIPYX((m92_vram_data[tile_index+3] & 0x6)>>1) | TILE_SPLIT(pri);
  185. }
  186.  
  187. static void get_pf3_wide_tile_info(int tile_index)
  188. {
  189.     int tile,color,pri;
  190.     tile_index = 4*tile_index + pf3_vram_ptr;
  191.  
  192.     tile=m92_vram_data[tile_index]+(m92_vram_data[tile_index+1]<<8);
  193.     color=m92_vram_data[tile_index+2];
  194.  
  195.     if (color&0x80) pri = 1;
  196.     else pri = 0;
  197.  
  198.     SET_TILE_INFO(0,tile,color&0x3f)
  199.     tile_info.flags = TILE_FLIPYX((m92_vram_data[tile_index+3] & 0x6)>>1) | TILE_SPLIT(pri);
  200. }
  201.  
  202. /*****************************************************************************/
  203.  
  204. READ_HANDLER( m92_vram_r )
  205. {
  206.     return m92_vram_data[offset];
  207. }
  208.  
  209. WRITE_HANDLER( m92_vram_w )
  210. {
  211.     int a,wide;
  212.  
  213.     m92_vram_data[offset]=data;
  214.  
  215.     /* Work out what area to dirty, potentially more than 1 */
  216.     a=offset&0xc000;
  217.     wide=offset&0x7fff;
  218.     offset&=0x3fff;
  219.  
  220.     if (RYPELEO_SPEEDUP) {
  221.         if (a==0xc000) {
  222.             tilemap_mark_tile_dirty(pf1_hlayer,offset/4);
  223.             return;
  224.         }
  225.         tilemap_mark_tile_dirty(pf1_layer,offset/4);
  226.     }
  227.     else
  228.     if (a==pf1_vram_ptr || (a==pf1_vram_ptr+0x4000)) {
  229.         tilemap_mark_tile_dirty(pf1_layer,offset/4);
  230.         tilemap_mark_tile_dirty(pf1_wide_layer,wide/4);
  231.     }
  232.  
  233.     if (a==pf2_vram_ptr)
  234.         tilemap_mark_tile_dirty(pf2_layer,offset/4);
  235.  
  236.     if (a==pf3_vram_ptr || (a==pf3_vram_ptr+0x4000)) {
  237.         tilemap_mark_tile_dirty(pf3_layer,offset/4);
  238.         tilemap_mark_tile_dirty(pf3_wide_layer,wide/4);
  239.     }
  240. }
  241.  
  242. /*****************************************************************************/
  243.  
  244. WRITE_HANDLER( m92_pf1_control_w )
  245. {
  246.     pf1_control[offset]=data;
  247. }
  248.  
  249. WRITE_HANDLER( m92_pf2_control_w )
  250. {
  251.     pf2_control[offset]=data;
  252. }
  253.  
  254. WRITE_HANDLER( m92_pf3_control_w )
  255. {
  256.     pf3_control[offset]=data;
  257. }
  258.  
  259. WRITE_HANDLER( m92_master_control_w )
  260. {
  261.     static int last_pf1_ptr,last_pf2_ptr,last_pf3_ptr;
  262.  
  263.     pf4_control[offset]=data;
  264.  
  265.     switch (offset) {
  266.         case 0: /* Playfield 1 (top layer) */
  267.             if ((pf4_control[0]&0x10)==0x10) pf1_enable=0; else pf1_enable=1;
  268.             if ((pf4_control[0]&0x40)==0x40) pf1_rowscroll=1; else pf1_rowscroll=0;
  269.             pf1_vram_ptr=(pf4_control[0]&3)*0x4000;
  270.             pf1_shape=(pf4_control[0]&4)>>2;
  271.  
  272.             if (RYPELEO_SPEEDUP) tilemap_set_enable(pf1_hlayer,pf1_enable);
  273.             if (pf1_shape) {
  274.                 tilemap_set_enable(pf1_layer,0);
  275.                 tilemap_set_enable(pf1_wide_layer,pf1_enable);
  276.             }
  277.             else {
  278.                 tilemap_set_enable(pf1_layer,pf1_enable);
  279.                 tilemap_set_enable(pf1_wide_layer,0);
  280.             }
  281.             /* Have to dirty tilemaps if vram pointer has changed */
  282.             if (m92_game_kludge!=1 && last_pf1_ptr!=pf1_vram_ptr) {
  283.                 tilemap_mark_all_tiles_dirty(pf1_layer);
  284.                 tilemap_mark_all_tiles_dirty(pf1_wide_layer);
  285.             }
  286.             last_pf1_ptr=pf1_vram_ptr;
  287.             break;
  288.         case 2: /* Playfield 2 (middle layer) */
  289.             if ((pf4_control[2]&0x10)==0x10) pf2_enable=0; else pf2_enable=1;
  290.             if ((pf4_control[2]&0x40)==0x40) pf2_rowscroll=1; else pf2_rowscroll=0;
  291.             tilemap_set_enable(pf2_layer,pf2_enable);
  292.             pf2_vram_ptr=(pf4_control[2]&3)*0x4000;
  293.             pf2_shape=(pf4_control[2]&4)>>2;
  294.             if (last_pf2_ptr!=pf2_vram_ptr)
  295.                 tilemap_mark_all_tiles_dirty(pf2_layer);
  296.             last_pf2_ptr=pf2_vram_ptr;
  297.             break;
  298.         case 4: /* Playfield 3 (bottom layer) */
  299.             if ((pf4_control[4]&0x10)==0x10) pf3_enable=0; else pf3_enable=1;
  300.             if ((pf4_control[4]&0x40)==0x40) pf3_rowscroll=1; else pf3_rowscroll=0;
  301.             pf3_shape=(pf4_control[4]&4)>>2;
  302.  
  303.             if (pf3_shape) {
  304.                 tilemap_set_enable(pf3_layer,0);
  305.                 tilemap_set_enable(pf3_wide_layer,pf3_enable);
  306.             }
  307.             else {
  308.                 tilemap_set_enable(pf3_layer,pf3_enable);
  309.                 tilemap_set_enable(pf3_wide_layer,0);
  310.             }
  311.             pf3_vram_ptr=(pf4_control[4]&3)*0x4000;
  312.             if (last_pf3_ptr!=pf3_vram_ptr) {
  313.                 tilemap_mark_all_tiles_dirty(pf3_layer);
  314.                 tilemap_mark_all_tiles_dirty(pf3_wide_layer);
  315.             }
  316.             last_pf3_ptr=pf3_vram_ptr;
  317.             break;
  318.         case 6:
  319.         case 7:
  320.             m92_raster_irq_position=((pf4_control[7]<<8) | pf4_control[6])-128;
  321.             if (!m92_raster_machine && m92_raster_enable && m92_raster_irq_position>128)
  322.                 usrintf_showmessage("WARNING!  RASTER IRQ ON NON-RASTER MACHINE DRIVER!");
  323.             break;
  324.     }
  325. }
  326.  
  327. /*****************************************************************************/
  328.  
  329. int m92_vh_start(void)
  330. {
  331.     if (RYPELEO_SPEEDUP) {
  332.         pf1_hlayer = tilemap_create(
  333.             get_pf1_htile_info,tilemap_scan_rows,
  334.             TILEMAP_TRANSPARENT | TILEMAP_SPLIT,
  335.             8,8,
  336.             64,64
  337.         );
  338.         pf1_layer = tilemap_create(
  339.                 get_pf1_ltile_info,tilemap_scan_rows,
  340.                 TILEMAP_TRANSPARENT | TILEMAP_SPLIT,
  341.                 8,8,
  342.                 64,64
  343.             );
  344.         pf1_hlayer->transmask[0] = 0xffff;
  345.         pf1_hlayer->transmask[1] = 0x00ff;
  346.         pf1_hlayer->transmask[2] = 0x0001;
  347.         pf1_hlayer->transparent_pen = 0;
  348.     }
  349.     else
  350.         pf1_layer = tilemap_create(
  351.             get_pf1_tile_info,tilemap_scan_rows,
  352.             TILEMAP_TRANSPARENT | TILEMAP_SPLIT,
  353.             8,8,
  354.             64,64
  355.         );
  356.  
  357.     pf2_layer = tilemap_create(
  358.         get_pf2_tile_info,tilemap_scan_rows,
  359.         TILEMAP_TRANSPARENT | TILEMAP_SPLIT,
  360.         8,8,
  361.         64,64
  362.     );
  363.  
  364.     pf3_layer = tilemap_create(
  365.         get_pf3_tile_info,tilemap_scan_rows,
  366.         TILEMAP_SPLIT,
  367.         8,8,
  368.         64,64
  369.     );
  370.  
  371.     pf1_wide_layer = tilemap_create(
  372.         get_pf1_wide_tile_info,tilemap_scan_rows,
  373.         TILEMAP_TRANSPARENT | TILEMAP_SPLIT,
  374.         8,8,
  375.         128,64
  376.     );
  377.  
  378.     pf3_wide_layer = tilemap_create(
  379.         get_pf3_wide_tile_info,tilemap_scan_rows,
  380.         TILEMAP_SPLIT,
  381.         8,8,
  382.         128,64
  383.     );
  384.  
  385.     if (!pf1_layer || !pf2_layer || !pf3_layer || !pf1_wide_layer || !pf3_wide_layer)
  386.         return 1;
  387.  
  388.     pf1_layer->transparent_pen = 0;
  389.     pf2_layer->transparent_pen = 0;
  390.     pf1_wide_layer->transparent_pen = 0;
  391.     /* split type 0 - totally transparent in front half */
  392.     pf1_layer->transmask[0] = 0xffff;
  393.     pf2_layer->transmask[0] = 0xffff;
  394.     pf3_layer->transmask[0] = 0xffff;
  395.     pf1_wide_layer->transmask[0] = 0xffff;
  396.     pf3_wide_layer->transmask[0] = 0xffff;
  397.     /* split type 1 - pens 0-7 transparent in front half */
  398.     pf1_layer->transmask[1] = 0x00ff;
  399.     pf2_layer->transmask[1] = 0x00ff;
  400.     pf3_layer->transmask[1] = 0x00ff;
  401.     pf1_wide_layer->transmask[1] = 0x00ff;
  402.     pf3_wide_layer->transmask[1] = 0x00ff;
  403.     /* split type 2 - pen 0 transparent in front half */
  404.     pf1_layer->transmask[2] = 0x0001;
  405.     pf2_layer->transmask[2] = 0x0001;
  406.     pf3_layer->transmask[2] = 0x0001;
  407.     pf1_wide_layer->transmask[2] = 0x0001;
  408.     pf3_wide_layer->transmask[2] = 0x0001;
  409.  
  410.     pf1_vram_ptr=pf2_vram_ptr=pf3_vram_ptr=0;
  411.     pf1_enable=pf2_enable=pf3_enable=0;
  412.     pf1_rowscroll=pf2_rowscroll=pf3_rowscroll=0;
  413.     pf1_shape=pf2_shape=pf3_shape=0;
  414.  
  415.     m92_sprite_list=0;
  416.     memset(spriteram,0,0x800);
  417.     memset(buffered_spriteram,0,0x800);
  418.  
  419.     return 0;
  420. }
  421.  
  422.  
  423. /*****************************************************************************/
  424.  
  425. static void mark_sprite_colours(void)
  426. {
  427.     int offs,color,i,j,pal_base,colmask[64];
  428.     unsigned int *pen_usage; /* Save some struct derefs */
  429.     int sprite_mask;
  430.  
  431.     sprite_mask=(Machine->drv->gfxdecodeinfo[1].gfxlayout->total)-1;
  432.  
  433.     pal_base = Machine->drv->gfxdecodeinfo[1].color_codes_start;
  434.     pen_usage=Machine->gfx[1]->pen_usage;
  435.     for (color = 0;color < 64;color++) colmask[color] = 0;
  436.  
  437.     if (m92_spritechip==0)
  438.         m92_sprite_list=(((0x100 - m92_spritecontrol[0])&0xff)*8)-8;
  439.     for (offs = m92_sprite_list;offs >= 0;offs -= 8)
  440.     {
  441.         int sprite,x_multi,y_multi,x,y,s_ptr;
  442.  
  443.         /* Save colours by skipping offscreen sprites */
  444.         y=(buffered_spriteram[offs+0] | (buffered_spriteram[offs+1]<<8))&0x1ff;
  445.         x=(buffered_spriteram[offs+6] | (buffered_spriteram[offs+7]<<8))&0x1ff;
  446.         if (x==0 || y==0) continue;
  447.  
  448.         sprite=buffered_spriteram[offs+2] | (buffered_spriteram[offs+3]<<8);
  449.         color=buffered_spriteram[offs+4]&0x3f;
  450.  
  451.         y_multi=(buffered_spriteram[offs+1]>>1)&0x3;
  452.         x_multi=(buffered_spriteram[offs+1]>>3)&0x3;
  453.  
  454.         y_multi=1 << y_multi; /* 1, 2, 4 or 8 */
  455.         x_multi=1 << x_multi; /* 1, 2, 4 or 8 */
  456.  
  457.         for (j=0; j<x_multi; j++)
  458.         {
  459.             s_ptr=8 * j;
  460.             for (i=0; i<y_multi; i++)
  461.             {
  462.                 colmask[color] |= pen_usage[(sprite + s_ptr)&sprite_mask];
  463.                 s_ptr++;
  464.             }
  465.         }
  466.     }
  467.  
  468.     for (color = 0;color < 64;color++)
  469.     {
  470.         for (i = 1;i < 16;i++)
  471.         {
  472.             if (colmask[color] & (1 << i))
  473.                 palette_used_colors[pal_base + 16 * color + i] = PALETTE_COLOR_USED;
  474.         }
  475.     }
  476. }
  477.  
  478. static void m92_drawsprites(struct osd_bitmap *bitmap, const struct rectangle *clip, int pri)
  479. {
  480.     int offs;
  481.  
  482.     /* The sprite list is now drawn *in reverse* from the control length */
  483.     for (offs = m92_sprite_list;offs >= 0;offs -= 8) {
  484.         int x,y,sprite,colour,fx,fy,x_multi,y_multi,i,j,s_ptr;
  485.  
  486.         if (((buffered_spriteram[offs+4]&0x80)==0x80) && pri==0) continue;
  487.         if (((buffered_spriteram[offs+4]&0x80)==0x00) && pri==1) continue;
  488.  
  489.         y=(buffered_spriteram[offs+0] | (buffered_spriteram[offs+1]<<8))&0x1ff;
  490.         x=(buffered_spriteram[offs+6] | (buffered_spriteram[offs+7]<<8))&0x1ff;
  491.         if (x==0 || y==0) continue; /* offscreen */
  492.  
  493.         x = x - 16;
  494.         y = 512 - 16 - y;
  495.  
  496.         sprite=(buffered_spriteram[offs+2] | (buffered_spriteram[offs+3]<<8));
  497.         colour=buffered_spriteram[offs+4]&0x3f;
  498.  
  499.         fx=buffered_spriteram[offs+5]&1;
  500.         fy=buffered_spriteram[offs+5]&2;
  501.         y_multi=(buffered_spriteram[offs+1]>>1)&0x3;
  502.         x_multi=(buffered_spriteram[offs+1]>>3)&0x3;
  503.  
  504.         y_multi=1 << y_multi; /* 1, 2, 4 or 8 */
  505.         x_multi=1 << x_multi; /* 1, 2, 4 or 8 */
  506.  
  507.         if (fx && x_multi>1) x+=16;
  508.         for (j=0; j<x_multi; j++)
  509.         {
  510.             s_ptr=8 * j;
  511.             if (!fy) s_ptr+=y_multi-1;
  512.  
  513.             for (i=0; i<y_multi; i++)
  514.             {
  515.                 drawgfx(bitmap,Machine->gfx[1],
  516.                         sprite + s_ptr,
  517.                         colour,
  518.                         fx,fy,
  519.                         x,y-i*16,
  520.                         clip,TRANSPARENCY_PEN,0);
  521.                 if (fy) s_ptr++; else s_ptr--;
  522.             }
  523.             if (fx) x-=16; else x+=16;
  524.         }
  525.     }
  526. }
  527.  
  528. /*****************************************************************************/
  529.  
  530. void m92_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  531. {
  532.     /* Screen refresh is handled by raster interrupt routine, here
  533.         we just check the keyboard */
  534.     if (keyboard_pressed_memory(KEYCODE_F1)) {
  535.         m92_raster_enable ^= 1;
  536.         if (m92_raster_enable)
  537.             usrintf_showmessage("Raster IRQ enabled");
  538.         else
  539.             usrintf_showmessage("Raster IRQ disabled");
  540.     }
  541. }
  542.  
  543. static void m92_update_scroll_positions(void)
  544. {
  545.     int i;
  546.  
  547.     /*    Playfield 3 rowscroll data is 0xdfc00 - 0xdffff
  548.         Playfield 2 rowscroll data is 0xdf800 - 0xdfbff
  549.         Playfield 1 rowscroll data is 0xdf400 - 0xdf7ff
  550.  
  551.         It appears to be hardwired to those locations.
  552.  
  553.         In addition, each playfield is staggered 2 pixels horizontally from the
  554.         previous one.  This is most obvious in Hook & Blademaster.
  555.  
  556.     */
  557.  
  558.     if (pf1_rowscroll) {
  559.         tilemap_set_scroll_rows(pf1_layer,512);
  560.         tilemap_set_scroll_rows(pf1_wide_layer,512);
  561.         for (i=0; i<1024; i+=2)
  562.             tilemap_set_scrollx( pf1_layer,i/2, (m92_vram_data[0xf400+i]+(m92_vram_data[0xf401+i]<<8)));
  563.         for (i=0; i<1024; i+=2)
  564.             tilemap_set_scrollx( pf1_wide_layer,i/2, (m92_vram_data[0xf400+i]+(m92_vram_data[0xf401+i]<<8))+256);
  565.     } else {
  566.         tilemap_set_scroll_rows(pf1_layer,1);
  567.         tilemap_set_scroll_rows(pf1_wide_layer,1);
  568.         tilemap_set_scrollx( pf1_layer,0, (pf1_control[5]<<8)+pf1_control[4] );
  569.         tilemap_set_scrollx( pf1_wide_layer,0, (pf1_control[5]<<8)+pf1_control[4]+256 );
  570.     }
  571.  
  572.     if (pf2_rowscroll) {
  573.         tilemap_set_scroll_rows(pf2_layer,512);
  574.         for (i=0; i<1024; i+=2)
  575.             tilemap_set_scrollx( pf2_layer,i/2, (m92_vram_data[0xf800+i]+(m92_vram_data[0xf801+i]<<8))-2);
  576.     } else {
  577.         tilemap_set_scroll_rows(pf2_layer,1);
  578.         tilemap_set_scrollx( pf2_layer,0, (pf2_control[5]<<8)+pf2_control[4]-2 );
  579.     }
  580.  
  581.     if (pf3_rowscroll) {
  582.         tilemap_set_scroll_rows(pf3_layer,512);
  583.         for (i=0; i<1024; i+=2)
  584.             tilemap_set_scrollx( pf3_layer,i/2, (m92_vram_data[0xfc00+i]+(m92_vram_data[0xfc01+i]<<8))-4);
  585.         tilemap_set_scroll_rows(pf3_wide_layer,512);
  586.         for (i=0; i<1024; i+=2)
  587.             tilemap_set_scrollx( pf3_wide_layer,i/2, (m92_vram_data[0xfc00+i]+(m92_vram_data[0xfc01+i]<<8))-4+256);
  588.     } else {
  589.         tilemap_set_scroll_rows(pf3_layer,1);
  590.         tilemap_set_scrollx( pf3_layer,0, (pf3_control[5]<<8)+pf3_control[4]-4 );
  591.         tilemap_set_scroll_rows(pf3_wide_layer,1);
  592.         tilemap_set_scrollx( pf3_wide_layer,0, (pf3_control[5]<<8)+pf3_control[4]-4+256 );
  593.     }
  594.  
  595.     tilemap_set_scrolly( pf1_layer,0, (pf1_control[1]<<8)+pf1_control[0] );
  596.     tilemap_set_scrolly( pf2_layer,0, (pf2_control[1]<<8)+pf2_control[0] );
  597.     tilemap_set_scrolly( pf3_layer,0, (pf3_control[1]<<8)+pf3_control[0] );
  598.     tilemap_set_scrolly( pf1_wide_layer,0, (pf1_control[1]<<8)+pf1_control[0] );
  599.     tilemap_set_scrolly( pf3_wide_layer,0, (pf3_control[1]<<8)+pf3_control[0] );
  600.  
  601.     if (m92_spritechip==1)
  602.         m92_sprite_list=0x800-8;
  603.  
  604.     if (RYPELEO_SPEEDUP) {
  605.         tilemap_set_scroll_rows(pf1_hlayer,1);
  606.         tilemap_set_scrollx( pf1_hlayer,0, (pf1_control[5]<<8)+pf1_control[4] );
  607.         tilemap_set_scrolly( pf1_hlayer,0, (pf1_control[1]<<8)+pf1_control[0] );
  608. //        pf1_hlayer->scrolled=1;
  609.     }
  610.  
  611. //    pf1_wide_layer->scrolled=1;
  612. //    pf3_wide_layer->scrolled=1;
  613. //    pf3_layer->scrolled=1;
  614. //    pf2_layer->scrolled=1;
  615. //    pf1_layer->scrolled=1;
  616. }
  617.  
  618. /*****************************************************************************/
  619.  
  620. static void m92_screenrefresh(struct osd_bitmap *bitmap,const struct rectangle *clip)
  621. {
  622.     if (pf3_shape) /* Updating all tilemaps causes palette overflow */
  623.         tilemap_update(pf3_wide_layer);
  624.     else
  625.         tilemap_update(pf3_layer);
  626.     tilemap_update(pf2_layer);
  627.     if (pf1_shape)
  628.         tilemap_update(pf1_wide_layer);
  629.     else
  630.         tilemap_update(pf1_layer);
  631.  
  632.     if (RYPELEO_SPEEDUP) tilemap_update(pf1_hlayer);
  633.  
  634.     /* This should be done once a frame only... but we can almost get away with it */
  635.     palette_init_used_colors();
  636.     mark_sprite_colours();
  637.     if (palette_recalc())
  638.         tilemap_mark_all_pixels_dirty(ALL_TILEMAPS);
  639.  
  640.     tilemap_render(ALL_TILEMAPS);
  641.  
  642.     if (pf3_enable) {
  643.         tilemap_draw(bitmap,pf3_wide_layer,TILEMAP_BACK);
  644.         tilemap_draw(bitmap,pf3_layer,TILEMAP_BACK);
  645.     }
  646.     else
  647.         fillbitmap(bitmap,palette_transparent_pen,clip);
  648.  
  649.     tilemap_draw(bitmap,pf2_layer,TILEMAP_BACK);
  650.     tilemap_draw(bitmap,pf1_wide_layer,TILEMAP_BACK);
  651.     if (RYPELEO_SPEEDUP && pf1_vram_ptr==0xc000)
  652.         tilemap_draw(bitmap,pf1_hlayer,TILEMAP_BACK);
  653.     else
  654.         tilemap_draw(bitmap,pf1_layer,TILEMAP_BACK);
  655.  
  656.     m92_drawsprites(bitmap,clip,0);
  657.  
  658.     tilemap_draw(bitmap,pf3_wide_layer,TILEMAP_FRONT);
  659.     tilemap_draw(bitmap,pf3_layer,TILEMAP_FRONT);
  660.     tilemap_draw(bitmap,pf2_layer,TILEMAP_FRONT);
  661.     tilemap_draw(bitmap,pf1_wide_layer,TILEMAP_FRONT);
  662.     if (RYPELEO_SPEEDUP && pf1_vram_ptr==0xc000)
  663.         tilemap_draw(bitmap,pf1_hlayer,TILEMAP_FRONT);
  664.     else
  665.         tilemap_draw(bitmap,pf1_layer,TILEMAP_FRONT);
  666.  
  667.     m92_drawsprites(bitmap,clip,1); /* These sprites are over all playfields */
  668. }
  669.  
  670. void m92_vh_raster_partial_refresh(struct osd_bitmap *bitmap,int start_line,int end_line)
  671. {
  672.     struct rectangle clip;
  673.  
  674.     clip.min_x = Machine->drv->visible_area.min_x;
  675.     clip.max_x = Machine->drv->visible_area.max_x;
  676.     clip.min_y = start_line+128;
  677.     clip.max_y = end_line+128;
  678.     if (clip.min_y < Machine->drv->visible_area.min_y)
  679.         clip.min_y = Machine->drv->visible_area.min_y;
  680.     if (clip.max_y > Machine->drv->visible_area.max_y)
  681.         clip.max_y = Machine->drv->visible_area.max_y;
  682.  
  683.     if (clip.max_y > clip.min_y)
  684.     {
  685.         m92_update_scroll_positions();
  686.         if (RYPELEO_SPEEDUP) tilemap_set_clip(pf1_hlayer,&clip);
  687.         tilemap_set_clip(pf1_layer,&clip);
  688.         tilemap_set_clip(pf2_layer,&clip);
  689.         tilemap_set_clip(pf3_layer,&clip);
  690.         tilemap_set_clip(pf1_wide_layer,&clip);
  691.         tilemap_set_clip(pf3_wide_layer,&clip);
  692.         m92_screenrefresh(bitmap,&clip);
  693.     }
  694. }
  695.